package ebedynky.controllers;

import ebedynky.beans.*;
import ebedynky.editors.EditorFactory;
import ebedynky.services.ProductService;
import ebedynky.services.ProductCategoryService;
import ebedynky.services.ProductGenusService;
import ebedynky.services.ProductSpecificationService;
import ebedynky.validators.ProductValidator;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

/**
 * @author davidon1
 */
@Controller
public class ProductController {

    /**
     * Initialises the data binder.
     * @param binder the data binder to be initialised
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(ProductCategory.class, EditorFactory.getCategoryIDEditor());
        binder.registerCustomEditor(ProductGenus.class, EditorFactory.getGenusIDEditor());
        binder.registerCustomEditor(ProductSpecification.class, EditorFactory.getSpecificationIDEditor());
        binder.setValidator(new ProductValidator());
    }

    /**
     * Fetches the index page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/product", method = RequestMethod.GET)
    public String getIndex(Model model) {
        return "product/index";
    }

    /**
     * Fetches the product adding page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/productAdd", method = RequestMethod.GET)
    public String getCreateForm(Model model) {
        model.addAttribute(new Product());
        return "product/createForm";
    }

    /**
     * Extracts the product data from the form,
     * validates them and stores them into the db.
     * @param product data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/productAdd", method = RequestMethod.POST)
    public String create(@Valid Product product, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "product/createForm";
        }
        ProductService ps = new ProductService();
        ps.addProduct(product);
        return "product/index";
    }

    /**
     * Fetches the product delete page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/productDel", method = RequestMethod.GET)
    public String getDeleteForm(Model model) {
        model.addAttribute(new Product());
        return "product/deleteForm";
    }

    /**
     * Deletes the corresponding product data from the db.
     * @param prd data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/productDel", method = RequestMethod.POST)
    public String delete(@Valid Product prd, BindingResult result) {
        if (result.hasErrors()) {
            return "product/deleteForm";
        }
        ProductService ps = new ProductService();
        ps.deleteProduct(prd.getProductID());
        return "product/index";

    }

    /**
     * Adds a product list extracted from the db as an attribute to the model.
     * @return List<Product> list of products
     */
    @ModelAttribute("productList")
    protected List<Product> productData() {
        ProductService ps = new ProductService();
        List<Product> list = ps.getAllProducts();
        return list;
    }

    /**
     * Adds a category list extracted from the db as an attribute to the model.
     * @return List<ProductCategory> list of categories
     */
    @ModelAttribute("categoryList")
    protected Map<Integer, String> categoryData() {
        Map<Integer, String> pcMap = new ConcurrentHashMap<Integer, String>();
        ProductCategoryService pcs = new ProductCategoryService();
        List<ProductCategory> list = pcs.getAllProductCategories();
        Iterator<ProductCategory> it = list.iterator();
        ProductCategory pc;
        while (it.hasNext()) {
            pc = it.next();
            pcMap.put(pc.getProductCategoryID(), pc.toString());
        }
        return pcMap;
    }

    /**
     * Adds a genus list extracted from the db as an attribute to the model.
     * @return List<ProductGenus> list of genuses
     */
    @ModelAttribute("genusList")
    protected List<ProductGenus> genusData() {
        ProductGenusService gs = new ProductGenusService();
        List<ProductGenus> list = gs.getAllProductGenuses();
        return list;
    }

    /**
     * Adds a specification list extracted from the db as an attribute to the model.
     * @return List<ProductSpecification> list of specifications
     */
    @ModelAttribute("specificationList")
    protected List<ProductSpecification> specificationData() {
        ProductSpecificationService ss = new ProductSpecificationService();
        List<ProductSpecification> list = ss.getAllProductSpecifications();
        return list;
    }
}
